package jumpingnotes.service.remoting;

import java.util.Date;
import java.util.Set;

import jumpingnotes.model.*;
import jumpingnotes.model.entity.*;

public class GroupServiceImpl extends GenericService implements GroupService {
	private final static int NOT_IN_GROUP = 0;
	private final static int IN_GROUP = 1;
	
	private boolean checkGruopOwner(String memberID, Group group)
	{
		if(group.getMember().getMemberId().equals(new Integer(memberID)))
				return true;
		else
			return false;
	}
	
	private boolean checkGroupAdmin(Member member,String groupID)
	{
		Set<GroupAdmin> s = member.getGroupAdmins();
		if(s != null && s.size() > 0)
		{
			for(GroupAdmin groupAdmin : s)
				if(groupAdmin.getGroupId() == Integer.parseInt(groupID))
					return true;
		}
		return false;
	}
	
	private int checkGroupMember(Member member, Group group)
	{		
		if (queryService.isMemberInGroup(member.getMemberId(), group.getGroupId())) {
			return IN_GROUP;
		} else {
			return NOT_IN_GROUP;
		}
	}
	
	public Result groupCreate(String memberID,String name, String intro, String image, String tag, String publicFlag)
	{
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		// create group
		Group group = new Group();
		group.setCreateTime(new Date());
		group.setUpdateTime(new Date());
		group.setName(name);
		group.setIntro(intro);
		group.setImage(image);
		group.setTag(tag);
		group.setPublicFlag(new Integer(publicFlag));
		group.setMember(member);
		group.setMemberCount(1);
		accessService.saveGroup(group);
		
		// member creating the group joins in the group
		GroupMember groupMember = new GroupMember();
		groupMember.setCreateTime(new Date());
		groupMember.setGroup(group);
		groupMember.setMember(member);
		accessService.saveGroupMember(groupMember);
		
		// set administrator
		GroupAdmin groupAdmin = new GroupAdmin();
		groupAdmin.setCreateTime(new Date());
		groupAdmin.setGroupId(group.getGroupId());
		groupAdmin.setMember(member);
		accessService.saveGroupAdmin(groupAdmin);

		ActivityTemplateParam[] activityParams = new ActivityTemplateParam[2];
		activityParams[0] = new ActivityTemplateParam();
		activityParams[0].setName("member");
		activityParams[0].setValue(member.getMemberId() + "&" + member.getNickName());
		activityParams[1] = new ActivityTemplateParam();
		activityParams[1].setName("group");
		activityParams[1].setValue(group.getGroupId() + "&" + group.getName());
		ActivityMediaItem[] mediaItems = new ActivityMediaItem[1];
		mediaItems[0] = new ActivityMediaItem();
		mediaItems[0].setMimeType(String.valueOf(ResourceTypes.TYPE_IMAGE));
		mediaItems[0].setUrl(group.getImage());		
		memberActivityCreate(memberID, ActivityType.GROUP_CREATE, activityParams, mediaItems, null, "1");				
		
		return new Result(group.getGroupId());
	}
	
	public Result groupImageUpload(String memberID, String groupID, String image)
	{
		// check
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if(group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		if(!checkGroupAdmin(member,groupID)) 
			return new Result(ErrorType.GROUP_NOT_ADMIN);
		group.setUpdateTime(new Date());
		group.setImage(image);
		accessService.updateGroup(group);
		
		ActivityTemplateParam[] activityParams = new ActivityTemplateParam[2];
		activityParams[0] = new ActivityTemplateParam();
		activityParams[0].setName("member");
		activityParams[0].setValue(member.getMemberId() + "&" + member.getNickName());
		activityParams[1] = new ActivityTemplateParam();
		activityParams[1].setName("group");
		activityParams[1].setValue(group.getGroupId() + "&" + group.getName());
		ActivityMediaItem[] mediaItems = new ActivityMediaItem[1];
		mediaItems[0] = new ActivityMediaItem();
		mediaItems[0].setMimeType(String.valueOf(ResourceTypes.TYPE_IMAGE));
		mediaItems[0].setUrl(group.getImage());		
		memberActivityCreate(memberID, ActivityType.GROUP_IMAGE_UPLOAD, activityParams, mediaItems, null, "1");						
		
		return new Result();
	}
	
	public Result groupPrivacyUpdate(String memberID, String groupID, String publicFlag)
	{
		// check
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if(group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		if(!checkGroupAdmin(member,groupID)) 
			return new Result(ErrorType.GROUP_NOT_ADMIN);
		
		group.setUpdateTime(new Date());
		group.setPublicFlag(new Integer(publicFlag));
		accessService.updateGroup(group);
		return new Result();
	}
	
	public Result groupInfoUpdate(String memberID, String groupID, String name, String intro, String tag)
	{
		// check
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if(group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		if(!checkGroupAdmin(member,groupID)) 
			return new Result(ErrorType.GROUP_NOT_ADMIN);

		// update group
		group.setUpdateTime(new Date());
		group.setName(name);
		group.setIntro(intro);
		group.setTag(tag);
		accessService.updateGroup(group);

		ActivityTemplateParam[] activityParams = new ActivityTemplateParam[2];
		activityParams[0] = new ActivityTemplateParam();
		activityParams[0].setName("member");
		activityParams[0].setValue(member.getMemberId() + "&" + member.getNickName());
		activityParams[1] = new ActivityTemplateParam();
		activityParams[1].setName("group");
		activityParams[1].setValue(group.getGroupId() + "&" + group.getName());
		ActivityMediaItem[] mediaItems = new ActivityMediaItem[1];
		mediaItems[0] = new ActivityMediaItem();
		mediaItems[0].setMimeType(String.valueOf(ResourceTypes.TYPE_IMAGE));
		mediaItems[0].setUrl(group.getImage());		
		memberActivityCreate(memberID, ActivityType.GROUP_INFO_UPDATE, activityParams, mediaItems, null, "1");						
		
		return new Result();
	}
	
	public Result groupJoin(String memberID, String groupID)
	{
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if(group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		if(group.getPublicFlag() == 0)
		{
			// check
			Member member = accessService.findMemberById(Integer.parseInt(memberID));
			if(member == null)
				return new Result(ErrorType.USER_NOT_EXIST);
			int state = checkGroupMember(member,group);
			if(state == NOT_IN_GROUP)
			{
    			GroupMember groupMember = new GroupMember();
    			groupMember.setCreateTime(new Date());
    			groupMember.setMember(member);
    			groupMember.setGroup(group);
    			accessService.saveGroupMember(groupMember);
    			group.setMemberCount(group.getMemberCount()+1);
    			accessService.updateGroup(group);
    			
    			ActivityTemplateParam[] activityParams = new ActivityTemplateParam[2];
    			activityParams[0] = new ActivityTemplateParam();
    			activityParams[0].setName("member");
    			activityParams[0].setValue(member.getMemberId() + "&" + member.getNickName());
    			activityParams[1] = new ActivityTemplateParam();
    			activityParams[1].setName("group");
    			activityParams[1].setValue(group.getGroupId() + "&" + group.getName());
    			ActivityMediaItem[] mediaItems = new ActivityMediaItem[1];
    			mediaItems[0] = new ActivityMediaItem();
    			mediaItems[0].setMimeType(String.valueOf(ResourceTypes.TYPE_IMAGE));
    			mediaItems[0].setUrl(group.getImage());		
    			memberActivityCreate(memberID, ActivityType.GROUP_JOIN, activityParams, mediaItems, null, "1");						
    			
    			return new Result();
			}
			else
				return new Result(ErrorType.GROUP_JOINED);
		}
		else
			return new Result(ErrorType.INVALID_GROUP_JOIN);
	}
	
	public Result groupInvite(String memberIDTo, String memberIDFrom, String groupID)
	{
		// check
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if(group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		
		Member memberTo = accessService.findMemberById(Integer.parseInt(memberIDTo));
		if(memberTo == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		
		Member memberFrom = accessService.findMemberById(Integer.parseInt(memberIDFrom));
		if(memberFrom == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		
		boolean fromFlag = false;
		boolean toFlag = false;
		Set<GroupMember> s = group.getGroupMembers();
		// exists
		if(s != null && s.size() >= 1)
			for(GroupMember groupMember : s)
			{
				if(groupMember.getMember().getMemberId().equals(memberFrom.getMemberId()))
					fromFlag = true;
				if(groupMember.getMember().getMemberId().equals(memberTo.getMemberId()))
					toFlag = true;
			}

		if(fromFlag == false)
			return new Result(ErrorType.INVALID_GROUP_INVITE);
		
		if(toFlag == false)
		{
			GroupMemberConfirm groupMemberConfirm = new GroupMemberConfirm();
			groupMemberConfirm.setCreateTime(new Date());
			groupMemberConfirm.setGroup(group);
			groupMemberConfirm.setMemberIdInvite(Integer.parseInt(memberIDFrom));
			groupMemberConfirm.setMember(memberTo);
			// what the message form?
			groupMemberConfirm.setMessage("");
			accessService.saveGroupMemberConfirm(groupMemberConfirm);
			return new Result();
		}
		else
			return new Result(ErrorType.GROUP_JOINED);
	}
	
	public Result groupInviteConfirm(String memberIDTo, String groupMemberConfirmID)
	{
		GroupMemberConfirm groupMemberConfirm = accessService.findGroupMemberConfirmById(Integer.parseInt(groupMemberConfirmID));
		if(groupMemberConfirm == null)
			return new Result(ErrorType.GROUP_CONFIRM_NOT_EXIST);
		//check
		Member memberTo = accessService.findMemberById(Integer.parseInt(memberIDTo));
		if(memberTo == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		
		if(groupMemberConfirm.getMember().getMemberId().equals(new Integer(memberIDTo)))
		{
			int state = checkGroupMember(memberTo,groupMemberConfirm.getGroup());
			Group group = null;
			if(state == NOT_IN_GROUP)
			{
    			GroupMember groupMember = new GroupMember();
    			group = groupMemberConfirm.getGroup();
    			groupMember.setCreateTime(new Date());
    			groupMember.setMember(memberTo);
    			groupMember.setMemberIdInvite(groupMemberConfirm.getMemberIdInvite());
    			groupMember.setGroup(group);
    			accessService.saveGroupMember(groupMember);
    			group.setMemberCount(group.getMemberCount()+1);
    			accessService.updateGroup(group);
			}
			accessService.deleteGroupMemberConfirm(groupMemberConfirm);
			if(state == NOT_IN_GROUP) {
    			ActivityTemplateParam[] activityParams = new ActivityTemplateParam[2];
    			activityParams[0] = new ActivityTemplateParam();
    			activityParams[0].setName("member");
    			activityParams[0].setValue(memberTo.getMemberId() + "&" + memberTo.getNickName());
    			activityParams[1] = new ActivityTemplateParam();
    			activityParams[1].setName("group");
    			activityParams[1].setValue(group.getGroupId() + "&" + group.getName());
    			ActivityMediaItem[] mediaItems = new ActivityMediaItem[1];
    			mediaItems[0] = new ActivityMediaItem();
    			mediaItems[0].setMimeType(String.valueOf(ResourceTypes.TYPE_IMAGE));
    			mediaItems[0].setUrl(group.getImage());		
    			memberActivityCreate(memberIDTo, ActivityType.GROUP_JOIN, activityParams, mediaItems, null, "1");														
				return new Result();
			}
			else
				return new Result(ErrorType.GROUP_JOINED);
		}
		else
			return new Result(ErrorType.INVALID_GROUP_CONFIRM);
	}
	
	public Result groupInviteDelete(String memberIDTo, String groupMemberConfirmID)
	{
		GroupMemberConfirm groupMemberConfirm = accessService.findGroupMemberConfirmById(Integer.parseInt(groupMemberConfirmID));
		if(groupMemberConfirm == null)
			return new Result(ErrorType.GROUP_CONFIRM_NOT_EXIST);
		Member memberTo = accessService.findMemberById(Integer.parseInt(memberIDTo));
		if(memberTo == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		if(groupMemberConfirm.getMember().getMemberId().equals(memberTo.getMemberId()))
		{
			accessService.deleteGroupMemberConfirm(groupMemberConfirm);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_GROUP_CONFIRM_DELETE);
	}
	
	public Result groupAdminPromote(String memberID,String groupID)
	{
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if(group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);

		if(!checkGroupAdmin(member,groupID))
		{
			GroupAdmin groupAdmin = new GroupAdmin();
			groupAdmin.setCreateTime(new Date());
			groupAdmin.setGroupId(group.getGroupId());
			groupAdmin.setMember(member);
			accessService.saveGroupAdmin(groupAdmin);
			return new Result();
		}
		else
			return new Result(ErrorType.GROUP_ADMIN);
	}
	
	public Result groupAdminDemote(String memberID,String groupID)
	{
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if(group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		
		if(checkGruopOwner(memberID,group))
			return new Result(ErrorType.INVALID_GROUP_DEMOTE);
		
		Set<GroupAdmin> s = member.getGroupAdmins();
		if(s != null && s.size() > 0)
		{
			for(GroupAdmin groupAdmin : s)
				if(groupAdmin.getGroupId() == Integer.parseInt(groupID))
				{
					s.remove(groupAdmin);
					accessService.deleteGroupAdmin(groupAdmin);
				}
		}
		return new Result();
	}
	
	public Result groupTopicCreate(String memberID,String groupID, String title, String body)
	{
		// check
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if(group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		if(checkGroupMember(member, group) == NOT_IN_GROUP)
			return new Result(ErrorType.INVALID_GROUP_TOPIC);
		GroupTopic groupTopic = new GroupTopic();
		groupTopic.setCreateTime(new Date());
		groupTopic.setUpdateTime(new Date());
		groupTopic.setGroup(group);
		groupTopic.setMember(member);
		groupTopic.setStatus(0);
		groupTopic.setTitle(title);
		groupTopic.setBody(body);
		accessService.saveGroupTopic(groupTopic);
		
		ActivityTemplateParam[] activityParams = new ActivityTemplateParam[3];
		activityParams[0] = new ActivityTemplateParam();
		activityParams[0].setName("member");
		activityParams[0].setValue(member.getMemberId() + "&" + member.getNickName());
		activityParams[1] = new ActivityTemplateParam();
		activityParams[1].setName("group");
		activityParams[1].setValue(group.getGroupId() + "&" + group.getName());
		activityParams[2] = new ActivityTemplateParam();
		activityParams[2].setName("topic");
		activityParams[2].setValue(title);
		ActivityMediaItem[] mediaItems = new ActivityMediaItem[1];
		mediaItems[0] = new ActivityMediaItem();
		mediaItems[0].setMimeType(String.valueOf(ResourceTypes.TYPE_IMAGE));
		mediaItems[0].setUrl(group.getImage());		
		memberActivityCreate(memberID, ActivityType.GROUP_TOPIC_CREATE, activityParams, mediaItems, null, "1");																
		
		return new Result(groupTopic.getGroupTopicId());
	}
	
	public Result groupTopicUpdate(String memberID,String groupTopicID, String title, String body)
	{
		GroupTopic groupTopic = accessService.findGroupTopicById(Integer.parseInt(groupTopicID));
		if(groupTopic == null)
			return new Result(ErrorType.GROUP_TOPIC_NOT_EXIST);
		// check
		if(groupTopic.getMember().getMemberId().equals(new Integer(memberID)))
		{
			groupTopic.setUpdateTime(new Date());
			groupTopic.setTitle(title);
			groupTopic.setBody(body);
			accessService.updateGroupTopic(groupTopic);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_GROUP_TOPIC_UPDATE);
	}
	
	public Result groupTopicDelete(String memberID,String groupTopicID)
	{
		// check
		GroupTopic groupTopic = accessService.findGroupTopicById(Integer.parseInt(groupTopicID));
		if(groupTopic == null)
			return new Result(ErrorType.GROUP_TOPIC_NOT_EXIST);
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		if(checkGroupAdmin(member,groupTopic.getGroup().getGroupId().toString()))
		{
			accessService.deleteGroupTopic(groupTopic);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_GROUP_TOPIC_DELETE);
	}
	
	public Result groupTopicCommentCreate(String memberID,String groupTopicID, String comment)
	{
		// check
		GroupTopic groupTopic = accessService.findGroupTopicById(Integer.parseInt(groupTopicID));
		if(groupTopic == null)
			return new Result(ErrorType.GROUP_TOPIC_NOT_EXIST);
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		GroupTopicComment groupTopicComment = new GroupTopicComment();
		groupTopicComment.setCreateTime(new Date());
		groupTopicComment.setBody(comment);
		groupTopicComment.setGroupTopic(groupTopic);
		groupTopicComment.setMember(member);
		groupTopicComment.setGroupId(groupTopic.getGroup().getGroupId());
		accessService.saveGroupTopicComment(groupTopicComment);

		Group group = groupTopic.getGroup();
		ActivityTemplateParam[] activityParams = new ActivityTemplateParam[3];
		activityParams[0] = new ActivityTemplateParam();
		activityParams[0].setName("member");
		activityParams[0].setValue(member.getMemberId() + "&" + member.getNickName());
		activityParams[1] = new ActivityTemplateParam();
		activityParams[1].setName("group");
		activityParams[1].setValue(group.getGroupId() + "&" + group.getName());
		activityParams[2] = new ActivityTemplateParam();
		activityParams[2].setName("topic");
		activityParams[2].setValue(groupTopic.getTitle());
		ActivityMediaItem[] mediaItems = new ActivityMediaItem[1];
		mediaItems[0] = new ActivityMediaItem();
		mediaItems[0].setMimeType(String.valueOf(ResourceTypes.TYPE_IMAGE));
		mediaItems[0].setUrl(group.getImage());		
		memberActivityCreate(memberID, ActivityType.GROUP_TOPIC_REPLY, activityParams, mediaItems, null, "1");																
				
		return new Result(groupTopicComment.getGroupTopicCommentId());
	}
	
	public Result groupTopicCommentDelete(String memberID, String groupTopicCommentID)
	{
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		GroupTopicComment groupTopicComment = accessService.findGroupTopicCommentById(Integer.parseInt(groupTopicCommentID));
		if(groupTopicComment == null)
			return new Result(ErrorType.GROUP_COMMENT_NOT_EXIST);
		if(checkGroupAdmin(member,groupTopicComment.getGroupId().toString()))
		{
			accessService.deleteGroupTopicComment(groupTopicComment);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_GROUP_COMMENT_DELETE);
	}
	
	public Result groupTopicSticky(String memberID, String groupTopicID)
	{
		// check
		GroupTopic groupTopic = accessService.findGroupTopicById(Integer.parseInt(groupTopicID));
		if(groupTopic == null)
			return new Result(ErrorType.GROUP_TOPIC_NOT_EXIST);
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);

		if(checkGroupAdmin(member,groupTopic.getGroup().getGroupId().toString()))
		{
			groupTopic.setUpdateTime(new Date());
			groupTopic.setStatus(1);
			accessService.updateGroupTopic(groupTopic);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_GROUP_TOPIC_STICKY);
	}
	
	public Result groupTopicUnsticky(String memberID, String groupTopicID)
	{
		// check
		GroupTopic groupTopic = accessService.findGroupTopicById(Integer.parseInt(groupTopicID));
		if(groupTopic == null)
			return new Result(ErrorType.GROUP_TOPIC_NOT_EXIST);
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		
		if(checkGroupAdmin(member,groupTopic.getGroup().getGroupId().toString()))
		{
			groupTopic.setUpdateTime(new Date());
			groupTopic.setStatus(0);
			accessService.updateGroupTopic(groupTopic);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_GROUP_TOPIC_UNSTICKY);
	}

	@Override
	public Result groupDelete(String groupID) {
		// TODO Auto-generated method stub
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if (group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		accessService.deleteGroup(Integer.parseInt(groupID));
		return new Result();
	}

	@Override
	public Result groupUpdate(String groupID, String name, String intro,
			String publicFlag) {
		// TODO Auto-generated method stub
		Group group = accessService.findGroupById(Integer.parseInt(groupID));
		if (group == null)
			return new Result(ErrorType.GROUP_NOT_EXIST);
		
		group.setName(name);
		group.setIntro(intro);
		group.setPublicFlag(Integer.parseInt(publicFlag));
		accessService.updateGroup(group);
		return new Result();
	}

	@Override
	public Result isMemberOfGroup(String memberID, String groupID) {
		// TODO Auto-generated method stub
		int memberId = Integer.parseInt(memberID);
		int groupId = Integer.parseInt(groupID);
		Member member = accessService.findMemberById(memberId);
		if (member == null) {
			return new Result(ErrorType.USER_NOT_EXIST);
		}
		Group group = accessService.findGroupById(groupId);
		if (group == null) {
			return new Result(ErrorType.GROUP_NOT_EXIST);
		}
		return new Result(queryService.isMemberInGroup(memberId, groupId));
	}
}
